﻿/* Copyright (C) 2006,2007 ScriptDevCN <http://silverwings.googlecode.com/>
*  本脚本汉化由银翼团队黑暗精灵完成
*/

/* ScriptData
SDName: boss_illidan_stormrage
SD%Complete: 80
SDComment: Need to do Eye Blast, Cage Traps, Enrage, Transform cosmetics and adjust timers.
EndScriptData */

/***************************************/
/* This script is still in development */
/*   by Wolfdragon and Moriquendu      */
/***************************************/

/******** Includes ************/
#include "../../sc_defines.h"
#include "../../../../../game/TargetedMovementGenerator.h"
#include "../../../../../shared/WorldPacket.h"
#include "../../../../../game/SpellAuras.h"
#include "../../../../../game/Player.h"
#include "../../../../../game/GossipDef.h"

/************* Quotes and Sounds ***********************/
// Gossip for when a player clicks Akama
#define GOSSIP_ITEM          "We are ready to face Illidan"

// Intro speech with Akama
#define SAY_INTRO_ILL1        " 阿卡玛，你的两面三刀并没有让我感到意外。我早就应该把你和你那些畸形的同胞全部杀掉！ "
#define SOUND_INTRO_ILL1    11463 // ~13 seconds
#define SAY_INTRO_AKA1        " 我们要终结你的统治，伊利丹。我的人民以及整个外域都将重获自由！ "
#define SOUND_INTRO_AKA1    11389 // ~12 seconds
#define SAY_INTRO_ILL2        " 说的好，但是这毫无意义！ "
#define SOUND_INTRO_ILL2    11464 // ~8 seconds
#define SAY_INTRO_AKA2        " 时机已到！目前已在眼前！ "
#define SOUND_INTRO_AKA2    11380 // ~5 seconds
#define SAY_INTRO_ILL3        " 你们这是自寻死路！ " // He conjectures that your level of preparation could perhaps be improved somewhat
#define SOUND_INTRO_ILL3    11466

// Signal for Akama to leave
#define SAY_AKAMA_MINION    "Come, my minions. Deal with this traitor as he deserves!"
#define SOUND_AKAMA_MINION  11465
#define SAY_AKAMA_LEAVE     "I'll deal with these mongrels. Strike now, friends! Strike at the betrayer!"
#define SOUND_AKAMA_LEAVE   11390

// Taunts?
#define SAY_HATRED          "I can feel your hatred"
#define SOUND_HATRED        11467
#define SAY_FEAR            "Give in to your fear!"
#define SOUND_FEAR          11468
#define SAY_POWER           "You know nothing of power!"
#define SOUND_POWER         11469
#define SAY_ARROGANCE       "Such..arrogance!"
#define SOUND_ARROGANCE     11471
#define SAY_RABBLE          " 你们这些乌合之众休想碰到我！ "
#define SOUND_RABBLE        11479

// Attacking Maeiv
#define SAY_ATT_MAIEV        "Feel the hatred of ten thousand years!"
#define SOUND_ATT_MAIEV        11470

// Self explanatory
#define SAY_KILL1            " 谁想成为下一个！ "
#define SOUND_KILL1            11473
#define SAY_KILL2            " 轻而易举！ "
#define SOUND_KILL2            11472

// I think I'll fly now and let my subordinates take you on
#define SAY_PHASE2            " 让埃辛诺斯的力量吞噬你们！ "
#define SOUND_PHASE2        11480

// When casting Eye Blast. Demon Fire will be appear on places that he casts this
#define SAY_EYE_BLAST      " 直视被判者的双眼吧！ "
#define SOUND_EYE_BLAST     11481

// kk, I go big, dark and demon on you.
#define SAY_MORPH            " 感受我体内的恶魔之力吧！ "
#define SOUND_MORPH            11475

// I KILL!
#define SAY_ENRAGE            " 你们浪费了我太多时间，去死吧！ "
#define SOUND_ENRAGE        11474

// Speech when Maiev enters
#define SAY_SUMMON_MAIEV    "Is this it, mortals? Is this all the fury you can muster?"
#define SOUND_SUMMON_MAIEV    11476 // ~8 seconds
#define SAY_MAIEV1            " 他们的愤怒和我的相比简直不值一提！伊利丹，我们之间终于要决一胜负了！ "
#define SOUND_MAIEV1        11491 // ~9 seconds
#define SAY_MAIEV_ILL2        " 玛维，你怎么可能！ "
#define SOUND_MAIEV_ILL2    11477 // ~7 seconds
#define SAY_MAIEV2            " 唉！我长久以来的追猎终于要结束了……今天，正义将得到申张！ "
#define SOUND_MAIEV2        11492 // ~10 seconds

// Death speech
#define SAY_DEATH_MAIEV1    " 唉！结束了，你被打败了。 "
#define SOUND_DEATH_MAIEV1    11496 // ~6 seconds
#define SAY_DEATH_ILL        " 你赢了，玛维！但是一个没有目标的猎手什么都不是！你离开了我，什么都不是…… "
#define SOUND_DEATH_ILL        11478 // ~22 seconds
#define SAY_DEATH_MAIEV2    " 他说的对！我觉得很失落，我什么都不是。 "
#define SOUND_DEATH_MAIEV2    11497 // ~9 seconds
#define SAY_DEATH_AKA        " 圣光会再次照耀这阴暗的太厅，我发誓！ "
#define SOUND_DEATH_AKA        11387 // ~8 seconds

/************** Spells *************/
// Normal Form
#define SPELL_SHEAR                     41032 // Reduces Max. Health by 60% for 7 seconds. Can stack 19 times. 1.5 second cast
#define SPELL_FLAME_CRASH               40832 // Summons an invis/unselect passive mob that has an aura of flame in a circle around him.
#define SPELL_DRAW_SOUL                 40904 // 5k Shadow Damage in front of him. Heals Illidan for 100k health (script effect)
#define SPELL_PARASITIC_SHADOWFIEND     41917 // DoT of 3k Shadow every 2 seconds. Lasts 10 seconds. (Script effect: Summon 2 parasites once the debuff has ticked off)
#define SPELL_AGONIZING_FLAMES          40932 // 4k fire damage initial to target and anyone w/i 5 yards. PHASE 3 ONLY
// Flying (Phase 2)
#define SPELL_FIREBALL                  40598 // 2.5k-3.5k damage in 10 yard radius. 2 second cast time.
#define SPELL_EYE_BLAST                 39908 // Fiery blue beam across platform. Deals ~20k fire damage, spawns Demon Fire on ground for 1 minute.
#define SPELL_DEMON_FIRE                40029 // Blue fire trail left by Eye Blast. Deals 2k per second if players stand on it.
#define SPELL_DARK_BARRAGE              40585 // 10 second channeled spell, 3k shadow damage per second.
// Demon Form
#define SPELL_DEMON_FORM                40506 // Transforms into Demon Illidan. Has an Aura of Dread on him.
#define SPELL_SHADOW_BLAST              41078 // 8k - 11k Shadow Damage. Targets highest threat. Has a splash effect, damaging anyone in 20 yards of the target.
#define SPELL_FLAME_BURST               41126 // Hurls fire at entire raid for ~3.5k damage every 10 seconds. Resistable. (Does not work: Script effect)
#define SPELL_FLAME_BURST_EFFECT        41131 // The actual damage. Have each player cast it on itself (workaround)
// Other Illidan spells
#define SPELL_KNEEL                     39656 // Before beginning encounter, this is how he appears (talking to skully).
#define SPELL_SHADOW_PRISON             40647 // Illidan casts this spell to immobilize entire raid when he summons Maiev.
#define SPELL_DEATH                     41220 // This spell doesn't do anything except stun Illidan and set him on his knees.
#define SPELL_SELF_ROOT                 42716 // Use this to disable Illidan from running to Akama during the Intro speech.

// Non-Illidan spells
#define SPELL_HEALING_POTION            40535 // Akama uses this to heal himself to full.
#define SPELL_GREEN_BEAM                39165 // Glaives cast it on Flames. Not sure if this is the right spell.
#define SPELL_PARALYZE                  41083 // Shadow Demons cast this on their target
#define SPELL_PURPLE_BEAM               39123 // Purple Beam connecting Shadow Demon to their target
#define SPELL_CAGE_TRAP_DUMMY           40761 // Put this in DB for cage trap GO.

/***** Locations *******/
// Locations for spawning glaives.
#define X_GLAIVE1                       695.105
#define X_GLAIVE2                       659.338
#define Y_GLAIVE                        305.303
#define Z_GLAIVE                        354.256

/**** Creature Summon IDs ****/
#define CREATURE_BLADE_OF_AZZINOTH      22996
#define CREATURE_FLAME_OF_AZZINOTH      22997
#define CREATURE_MAIEV_SHADOWSONG       23197
#define CREATURE_SHADOW_DEMON           23375

struct Yells
{
    float sound;
    char* text;
    char* creature;
    uint32 timer, emote;
    bool Talk;
};

static Yells Conversation[]=
{
    {11463, "Akama... your duplicity is hardly surprising. I should have slaughtered you and your malformed brethren long ago.", "Illidan", 8000, 0, true},
    {0, NULL, "Illidan", 5000, 396, true}, 
    {11389, "We've come to end your reign, Illidan. My people and all of Outland shall be free!", "Akama", 7000, 25, true},
    {0, NULL, "Akama", 5000, 66, true},
    {11464, "Boldly said. But I remain unconvinced.", "Illidan", 8000, 396, true},
    {11380, "The time has come! The moment is at hand!", "Akama", 3000, 22, true},
    {0, NULL, "Akama", 2000, 15, true},
    {11466, "You are not prepared!", "Illidan", 3000, 406, true},
    {0, NULL, "Empty", 0, true},
    {0, NULL, "Empty", 0, false},
    {11476, "Is this it, mortals? Is this all the fury you can muster?", "Illidan", 8000, 0, true},
    {11491, "Their fury pales before mine, Illidan. We have some unsettled business between us.", "Maiev", 9000, 0, true},
    {11477, "Maiev... How is this even possible?", "Illidan", 7000, 0, true},
    {11492, "Ah... my long hunt is finally over. Today, Justice will be done!", "Maiev", 10000, 0, true},
    {11470, "Feel the hatred of ten thousand years!", "Illidan", 1000, 0, false},
    {11496, "Ahh... It is finished. You are beaten.", "Maiev", 6000, 0, true},
    {11478, "You have won... Maiev...but the huntress... is nothing...without the hunt... you... are nothing... without me..", "Illidan", 22000, 0, true},
    {11497, "He is right. I feel nothing... I am nothing... Farewell, champions.", "Maiev", 9000, 0, true},
    {11387, "The Light will fill these dismal halls once again. I swear it.", "Akama", 8000, 0, true}
};

static Yells RandomTaunts[]=
{
    {11467, "I can feel your hatred", "Illidan", 0, 0, false},
    {11468, "Give in to your fear!", "Illidan", 0, 0, false},
    {11469, "You know nothing of power!", "Illidan", 0, 0, false},
    {11471, "Such... arrogance!", "Illidan", 0, 0, false},
    {11479, "I will not be touched by rabble such as you!", "Illidan", 0, 0, false}
};

struct Locations
{
    float x, y, z;
};

static Locations Flight[]=
{
    {692, 331, 353},
    {713, 309, 366},
    {687, 271, 353},
    {650, 285, 353},
    {653, 331, 371}
};

/******* The AI *******/
struct MANGOS_DLL_SPEC boss_illidan_stormrageAI : public ScriptedAI
{
    boss_illidan_stormrageAI(Creature* c) : ScriptedAI(c)
    {
        pInstance = ((ScriptedInstance*)c->GetInstanceData());
        SetVariables();
    }

    /** Instance Data **/
    ScriptedInstance* pInstance;

    /** Generic **/
    bool InCombat;
    bool IsTalking;
    bool HasSummoned;
    uint32 Phase;
    uint32 GlobalTimer;
    uint32 TalkCount;
    uint32 DemonFormSequence;

    /** GUIDs **/
    uint64 FlameGUID[1];
    uint64 GlaiveGUID[1];
    uint64 AkamaGUID;
    uint64 MaievGUID;

    /** Timers **/
    uint32 ShearTimer;
    uint32 DrawSoulTimer;
    uint32 FlameCrashTimer;
    uint32 ParasiticShadowFiendTimer;
    uint32 FlyTimer;
    uint32 FireballTimer;
    uint32 EyeBlastTimer;
    uint32 DarkBarrageTimer;
    uint32 AgonizingFlamesTimer;
    uint32 ShadowBlastTimer;
    uint32 FlameBurstTimer;
    uint32 FlameBurstExplosionTimer;
    uint32 ShadowDemonTimer;
    uint32 SummonTimer;
    uint32 TalkTimer;
    uint32 TransformTimer;
    uint32 EnrageTimer;
    uint32 AnimationTimer;
    uint32 TauntTimer; // This is used for his random yells

    void SetVariables()
    {
        Phase = 1;
        /*   1 = Normal form
             2 = Flying. Raid attacks Flames of Azzinoth
             3 = Normal form, casts Agonizing Flames + can transform to Demon form
             4 = Demon Form.
             5 = Normal form with Agonizing Flames + Demon form + Maiev
        */

        // If in combat, check if any flames/glaives are alive/existing. Kill if alive and set GUIDs to 0
        for(uint8 i = 0; i < 2; i++)
        {
            if(FlameGUID[i])
            {
                if(InCombat)
                {
                    Unit* Flame = Unit::GetUnit((*m_creature), FlameGUID[i]);
                    if(Flame) Flame->DealDamage(Flame, Flame->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                }
                FlameGUID[i] = 0;
            }

            if(GlaiveGUID[i])
            {
                if(InCombat)
                {
                    Unit* Glaive = Unit::GetUnit((*m_creature), GlaiveGUID[i]);
                    if(Glaive) Glaive->DealDamage(Glaive, Glaive->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                }
                GlaiveGUID[i] = 0;
            }
        }

        InCombat = false;
        IsTalking = false;
        HasSummoned = false;
        AkamaGUID = 0;
        MaievGUID = 0;
        GlobalTimer = 0;
        TalkCount = 0;
        TalkTimer = 0;
        DemonFormSequence = 0;

        /** Normal Form **/
        ShearTimer = 20000 + (rand()%10 * 100); // 20 to 30 seconds
        FlameCrashTimer = 30000; //30 seconds
        ParasiticShadowFiendTimer = 25000; // 25 seconds
        DrawSoulTimer = 35000; // 35 seconds

        /** Phase 2 **/
        FlyTimer = 20000; // Make him fly to various spots
        SummonTimer = 10000; // Phase 2 timers may be incorrect
        FireballTimer = 5000;
        DarkBarrageTimer = 45000;
        EyeBlastTimer = 30000;

        /** Phase 3+ **/
        AgonizingFlamesTimer = 35000; // Phase 3+ timers may be incorrect
        ShadowBlastTimer = 3000;
        FlameBurstTimer = 20000;
        FlameBurstExplosionTimer = 22000;
        ShadowDemonTimer = 15000;
        TransformTimer = 60000;
        EnrageTimer = 15000;
        AnimationTimer = 0;

        TauntTimer = 30000; // This timer may be off.

        DoCast(m_creature, SPELL_SELF_ROOT, true);
        if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
            m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // SPELL_SELF_ROOT adds the skinning flag to m_creature...
        DoCast(m_creature, SPELL_KNEEL); // Illidan starts off talking to skully
        m_creature->setFaction(35); // Start him off as friendly.
        m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);    
    }

    void EnterEvadeMode()
    {
        SetVariables();

        m_creature->RemoveAllAuras();
        m_creature->DeleteThreatList();
        m_creature->CombatStop();
        DoGoHome();
    }

    void AttackStart(Unit *who)
    {
        if(!who || IsTalking || Phase == 2)
            return;
        
        if (who->isTargetableForAttack() && who!= m_creature)
        {
            //Begin melee attack if we are within range
            DoStartMeleeAttack(who);

            if (!InCombat) InCombat = true;
        }
    }

    void MoveInLineOfSight(Unit *who)
    {
        if (!who || m_creature->getVictim())
            return;

        if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
        {
            float attackRadius = m_creature->GetAttackDistance(who);
            if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && m_creature->IsWithinLOSInMap(who))
            {
                if(who->HasStealthAura())
                    who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);

                if (!InCombat) InCombat = true;

                DoStartMeleeAttack(who);
            }
        }
    }

    void JustDied(Unit *killer)
    {
        SetVariables(); // Reset variables for respawn.
        m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
    }

    void KilledUnit(Unit *victim)
    {
        if(victim == m_creature) return;

        switch(rand()%2)
        {
            case 0:
                DoYell(SAY_KILL1, LANG_UNIVERSAL, victim);
                DoPlaySoundToSet(m_creature, SOUND_KILL1);
                break;
            case 1:
                DoYell(SAY_KILL2, LANG_UNIVERSAL, victim);
                DoPlaySoundToSet(m_creature, SOUND_KILL2);
                break;
        }
    }

    /** This is a workaround so that he actually does his blade animations when melee'ing **/
    void DoMeleeAttackIfReadyWithAnimations()
    {
        //If we are within range melee the target
        if( m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
        {
            //Make sure our attack is ready and we arn't currently casting
            if( m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
            {
                switch(rand()%3)
                {
                    case 0:
                        m_creature->HandleEmoteCommand(389);
                        break;
                    case 1:
                        m_creature->HandleEmoteCommand(390);
                        break;
                    case 2:
                        m_creature->HandleEmoteCommand(36);
                        break;
                }
                m_creature->AttackerStateUpdate(m_creature->getVictim());
                m_creature->resetAttackTimer();
            }
        }
    }

    /** This will handle the cast of eye blast **/
    void CastEyeBlast()
    {
        m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
        DoYell(SAY_EYE_BLAST, LANG_UNIVERSAL, NULL);
        DoPlaySoundToSet(m_creature, SOUND_EYE_BLAST);
    }

    /** Workaround for the Flame Burst so that it actually does damage **/
    void DoFlameBurstExplosion()
    {
        std::list<HostilReference *> m_threatlist = m_creature->getThreatManager().getThreatList();
        if(!m_threatlist.size()) return;
        std::list<Unit *> targets;
        std::list<HostilReference *>::iterator itr = m_threatlist.begin();
        std::advance(itr, 0);
        for( ; itr != m_threatlist.end(); ++itr)
        {
            Unit* pUnit = Unit::GetUnit((*m_creature), (*itr)->getUnitGuid());
            if(pUnit && pUnit->isAlive()) // Check if pUnit exists and is alive
                pUnit->CastSpell(pUnit, SPELL_FLAME_BURST_EFFECT, true); // Have the player cast the flame burst effect on themself
        }
    }

    void ResetThreat()
    {
        std::list<HostilReference*>& m_threatlist = m_creature->getThreatManager().getThreatList();
        std::list<HostilReference*>::iterator i = m_threatlist.begin();
        for(i = m_threatlist.begin(); i != m_threatlist.end(); ++i)
        {
            Unit* pUnit = NULL;
            pUnit = Unit::GetUnit((*m_creature), (*i)->getUnitGuid());
            if(pUnit)
                m_creature->getThreatManager().modifyThreatPercent(pUnit, -100);
        }
    }

    void Talk(uint32 count)
    {
        uint32 sound = Conversation[count].sound;
        char* text = Conversation[count].text;
        TalkTimer = Conversation[count].timer;
        uint32 emote = Conversation[count].emote;
        IsTalking = Conversation[count].Talk;
        if(Conversation[count].creature == "Illidan")
        {
            if(text)
                DoYell(text, LANG_UNIVERSAL, NULL);
            m_creature->HandleEmoteCommand(emote);
            if(sound)
                DoPlaySoundToSet(m_creature, sound);
        }
        else if(Conversation[count].creature == "Akama")
        {
            if(!AkamaGUID)
            {
                if(pInstance)
                {
                    AkamaGUID = pInstance->GetData64("Akama");
                    if(!AkamaGUID) return;
                }
            }

            Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID));
            if(Akama)
            {
                if(text)
                    Akama->Yell(text, LANG_UNIVERSAL, NULL);
                Akama->HandleEmoteCommand(emote);
                if(sound)
                    DoPlaySoundToSet(Akama, sound);
            }
        }
        else if(Conversation[count].creature == "Maiev")
        {
            if(!MaievGUID) return;
            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
            if(Maiev)
            {
                if(text)
                    Maiev->Yell(text, LANG_UNIVERSAL, NULL);
                Maiev->HandleEmoteCommand(emote);
                if(sound)
                    DoPlaySoundToSet(Maiev, sound);
            }
        }
        else if(Conversation[count].creature == "Empty") // This is just for special cases without speech/sounds/emotes.
            return; 
    }
    
    void Move(float X, float Y, float Z, uint32 Time, Creature* c, uint32 flags = 0x0200)
    {
        WorldPacket data( SMSG_MONSTER_MOVE, (41+c->GetPackGUID().size()) );
        data.append(c->GetPackGUID());

        data << c->GetPositionX() << c->GetPositionY() << c->GetPositionZ();
        // unknown field - unrelated to orientation
        // seems to increment about 1000 for every 1.7 seconds
        // for now, we'll just use mstime
        data << getMSTime();

        data << uint8(0);                                // walkback when walking from A to B
        data << uint32(flags);          // flags

        data << Time;                                           // Time in between points
        data << uint32(1);                                      // 1 single waypoint
        data << X << Y << Z;                                    // the single waypoint Point B
        c->SendMessageToSet( &data, true );
        c->Relocate(X, Y, Z);
    }

    void UpdateAI(const uint32 diff)
    {
        /*** This section will handle the conversations ***/
        if(IsTalking) // Is there a better way to do this without a long switch statement?
        {
            if(TalkTimer < diff)
            {
                m_creature->RemoveAurasDueToSpell( SPELL_KNEEL );
                switch(TalkCount) // This is only for specialized cases
                {
                    case 8:
                        m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479);
                        m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481);
                        m_creature->HandleEmoteCommand(406);
                        m_creature->RemoveAurasDueToSpell( SPELL_SELF_ROOT );
                        m_creature->setFaction(14);
                        break;
                    case 9:
                        DoYell("Case 9", LANG_UNIVERSAL, NULL);
                        if(AkamaGUID)
                        {
                            DoYell("Acquiring Akama GUID", LANG_UNIVERSAL, NULL);
                            Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID));
                            if(Akama)
                            {
                                DoYell("Akama", LANG_UNIVERSAL, NULL);
                                Akama->RemoveAurasDueToSpell( SPELL_SELF_ROOT ); // Unaura Akama
                                m_creature->AI()->AttackStart(Akama); // Start attacking Akama
                                Akama->AI()->AttackStart(m_creature); // Akama starts attacking us
                            }
                        }
                        m_creature->RemoveAllAuras(); // Remove any auras we have on us
                        m_creature->setFaction(14); // Make him hostile after Intro is done.
                        break;
                    case 14:
                        DoYell("Case 14", LANG_UNIVERSAL, NULL);
                        if(MaievGUID)
                        {
                            DoYell("Maiev GUID", LANG_UNIVERSAL, NULL);
                            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
                            if(Maiev)
                            {
                                DoYell("Maiev", LANG_UNIVERSAL, NULL);
                                Maiev->AI()->AttackStart(m_creature); // FOrce Maiev to attack us.
                                Maiev->AddThreat(m_creature, 10000000.0f); // Have Maiev add a lot of threat on us so that players don't pull her off
                            }
                        }
                        break;
                    case 15:
                        if(AkamaGUID)
                        {
                            Creature* Akama = ((Creature*)Unit::GetUnit((*m_creature), AkamaGUID));
                            if(Akama) // Make Akama visible and move towards us for the final talk.
                            {
                                Akama->RemoveAllAuras(); // Remove SPELL_SELF_ROOT from Akama if he has it along with any other buffs.
                                Akama->SetVisibility(VISIBILITY_ON);
                                Move(m_creature->GetPositionX()+10, m_creature->GetPositionY()+5, m_creature->GetPositionZ(), 5000, Akama);
                            }                        
                        }
                        break;
                    case 18: // Kill ourself.
                        if(MaievGUID)
                        {
                            Creature* Maiev = ((Creature*)Unit::GetUnit((*m_creature), MaievGUID));
                            if(Maiev) // Make Maiev leave
                            {
                                Maiev->SetVisibility(VISIBILITY_OFF); // Close enough....
                            }
                        }
                        m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                        break;
                    
                }
                Talk(TalkCount); // This function does most of the talking
                TalkCount++;
            }else TalkTimer -= diff;
        }

        // If we don't have a target, check if we are not doing kneel animation, recast if false then return.
        if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || IsTalking) return;

        /** Signal to change to phase 2 **/
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 65) && (Phase == 1))
        {
            SummonTimer = 10000;
            Phase = 2;
            m_creature->SetHover(true);
            m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF);
            m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
            m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
            (*m_creature).GetMotionMaster()->Clear();
        }

        /** Signal to summon Maiev **/
        if(((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 30) && (!MaievGUID))
        {
            Creature* Maiev = NULL;
            //TODO: FIND EXACT LOCATIONS
            Maiev = m_creature->SummonCreature(23197, m_creature->GetPositionX() + 10, m_creature->GetPositionY() + 5, m_creature->GetPositionZ(), 0, TEMPSUMMON_DEAD_DESPAWN, 0);
            if(Maiev)
            {
                DoCast(m_creature, SPELL_SHADOW_PRISON);
                TalkCount = 10;
                IsTalking = true;
                MaievGUID = Maiev->GetGUID();
                DoFaceTarget(Maiev);
                Maiev->SetInFront(m_creature);
            }
        }

        /** Time for the death speech **/
        if((m_creature->GetHealth()*100 / m_creature->GetMaxHealth() < 3) && (!IsTalking))
        {
            DoCast(m_creature, SPELL_DEATH);
            m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
            (*m_creature).GetMotionMaster()->Clear();
            IsTalking = true;
            TalkCount++;
        }


        /***** Spells for Phase 1, 3 and 5 (Normal Form) ******/
        if(Phase == 1 || Phase == 3 || Phase == 5)
        {
            if(TauntTimer < diff)
            {
                uint32 random = rand()%5;
                char* text = RandomTaunts[random].text;
                uint32 sound = RandomTaunts[random].sound;
                DoYell(text, LANG_UNIVERSAL, NULL);
                DoPlaySoundToSet(m_creature, sound);
                TauntTimer = 30000;
            }else TauntTimer -= diff;

            if(GlobalTimer < diff) // Global Timer so that spells do not overlap.
            {
                if(ShearTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_SHEAR);
                    ShearTimer = 20000 + (rand()%10 * 100);
                    GlobalTimer += 2000;
                }else ShearTimer -= diff;

                if(FlameCrashTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_FLAME_CRASH);
                    FlameCrashTimer = 30000;
                    GlobalTimer += 2000;
                }else FlameCrashTimer -= diff;

                if(ParasiticShadowFiendTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_PARASITIC_SHADOWFIEND);
                    ParasiticShadowFiendTimer = 25000;
                }else ParasiticShadowFiendTimer -= diff;

                if(DrawSoulTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_DRAW_SOUL);
                    DrawSoulTimer = 35000;
                    GlobalTimer = 3000;
                }else DrawSoulTimer -= diff;
            }else GlobalTimer -= diff;

            DoMeleeAttackIfReadyWithAnimations();
        }

        /*** Phase 2 ***/
        if(Phase == 2)
        {
            // Check if Summon Timer is not 0 or null.
            if(!HasSummoned)
            {
                if(SummonTimer < diff)
                {
                    Creature* Flame1 = NULL;
                    Creature* Flame2 = NULL;
                    Creature* Glaive1 = NULL;
                    Creature* Glaive2 = NULL;

                    // Summon Glaives.
                    Glaive1 = m_creature->SummonCreature(CREATURE_BLADE_OF_AZZINOTH, X_GLAIVE1, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                    Glaive2 = m_creature->SummonCreature(CREATURE_BLADE_OF_AZZINOTH, X_GLAIVE2, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_DESPAWN, 0);

                    // Summon Flames near the Glaives and have the Glaives channel a green beam on the flames
                    if(Glaive1)
                    {
                        GlaiveGUID[0] = Glaive1->GetGUID();
                        Flame1 = m_creature->SummonCreature(22997, X_GLAIVE1-5, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);
                        if(Flame1)
                        {
                            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                            Flame1->Attack(target);
                            FlameGUID[0] = Flame1->GetGUID();
                            Glaive1->CastSpell(Flame1, SPELL_GREEN_BEAM, true);
                        }
                    }

                    if(Glaive2)
                    {
                        GlaiveGUID[1] = Glaive2->GetGUID();
                        Flame2 = m_creature->SummonCreature(22997, X_GLAIVE2+5, Y_GLAIVE, Z_GLAIVE, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000);
                        if(Flame2)
                        {
                            Unit* target = SelectUnit(SELECT_TARGET_RANDOM, 0);
                            Flame2->Attack(target);
                            FlameGUID[1] = Flame2->GetGUID();
                            Glaive2->CastSpell(Flame2, SPELL_GREEN_BEAM, true);
                        }
                    }
                    HasSummoned = true;
                }else SummonTimer -= diff;
            }

            //  Check if we are hovering. Recast if we are not.
            if(!m_creature->isHover()) m_creature->SetHover(true);

            if(HasSummoned)
            {
                // Check if flames are dead or non-existant. If so, set GUID to 0.
                for(uint8 i = 0; i < 2; i++)
                {
                    if(FlameGUID[i])
                    {
                        Unit* Flame = NULL;
                        Flame = Unit::GetUnit((*m_creature), FlameGUID[i]);

                        if(!Flame || !Flame->isAlive())
                            FlameGUID[i] = 0;
                    }
                }

                // If both flames are dead/non-existant, kill glaives and change to phase 3.
                if(!FlameGUID[0] && !FlameGUID[1])
                {
                    for(uint8 i = 0; i < 2; i++)
                    {
                        if(GlaiveGUID[i])
                        {
                            Unit* Glaive = NULL;
                            Glaive = Unit::GetUnit((*m_creature), GlaiveGUID[i]);
                            if(Glaive)
                                Glaive->DealDamage(Glaive, Glaive->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_NORMAL, NULL, 0, false);
                            GlaiveGUID[i] = 0;
                        }
                    }
                    m_creature->SetHover(false);
                    m_creature->HandleEmoteCommand(EMOTE_ONESHOT_LAND);
                    Phase = 3;
                    m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                    (*m_creature).GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim()));
                    m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479);
                    m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481);
                }
            }

            if(GlobalTimer < diff)
            {
                if(FlyTimer < diff)
                {
                    uint32 random = rand()%5;
                    Move(Flight[random].x, Flight[random].y, Flight[random].z, 3000, m_creature);
                    FlyTimer = 15000;
                    GlobalTimer = 3000;
                }else FlyTimer -= diff;

                if(FireballTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FIREBALL);
                    FireballTimer = 5000;
                    GlobalTimer += 1500;
                }else FireballTimer -= diff;

                if(DarkBarrageTimer < diff)
                {
                    m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DARK_BARRAGE);
                    DarkBarrageTimer = 45000;
                    GlobalTimer += 11000;
                }else DarkBarrageTimer -= diff;

                if(EyeBlastTimer < diff)
                {
                    CastEyeBlast();
                    EyeBlastTimer = 30000;
                    GlobalTimer += 40000;
                }else EyeBlastTimer -= diff;
            }else GlobalTimer -= diff;
        }

        /** Phase 3,5 spells only**/
        if(Phase == 3 || Phase == 5)
        {
            if(GlobalTimer < diff)
            {
                if(AgonizingFlamesTimer < diff)
                {
                    DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_AGONIZING_FLAMES);
                    AgonizingFlamesTimer = 35000;
                    GlobalTimer += 1500;
                }else AgonizingFlamesTimer -= diff;
            }else GlobalTimer -= diff;
           
            if(TransformTimer < diff)
            {
                Phase = 6; // Transform sequence
                DemonFormSequence = 0;
                AnimationTimer = 0;
                ResetThreat(); // Reset Threat list
                DoYell(SAY_MORPH, LANG_UNIVERSAL, NULL);
                DoPlaySoundToSet(m_creature, SOUND_MORPH);
                TransformTimer = 30000;
                (*m_creature).GetMotionMaster()->Clear(); // Stop moving
            }else TransformTimer -= diff;
        }

        /** Phase 4 spells only (Demon Form) **/
        if(Phase == 4)
        {
            // Stop moving if we are by clearing movement generators.
            if(!m_creature->GetMotionMaster()->empty())
                (*m_creature).GetMotionMaster()->Clear();

            // Reaura ourself with SELF_ROOT_SELF if we are not already rooted.
            if(!m_creature->HasAura(SPELL_SELF_ROOT, 0))
                DoCast(m_creature, SPELL_SELF_ROOT, true);

            if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE)) // SPELL_SELF_ROOT adds the skinning flag for some reason..
                m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);

            if(TransformTimer < diff)
            {
                Phase = 6;
                DemonFormSequence = 5;
                AnimationTimer = 0;
                ResetThreat(); // Reset again
                m_creature->RemoveAurasDueToSpell(SPELL_DEMON_FORM);
                if(!MaievGUID) Phase = 3; // Maiev has not yet been summoned, go back to phase 3
                else Phase = 5; // Maiev has been summoned, go to phase 5.
                (*m_creature).GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim()));
                TransformTimer = 30000;
            }else TransformTimer -= diff;

            if(ShadowDemonTimer < diff)
            {
                m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
                Creature* ShadowDemon = NULL;
                for(uint8 i = 0; i < 4; i++)
                {
                    Unit* target = NULL;
                    if(target)
                    {
                        ShadowDemon = m_creature->SummonCreature(23375, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 0);
                        if(ShadowDemon)
                        {
                            ShadowDemon->Attack(target);
                            ShadowDemon->AddThreat(target, 5000000.0f);
                            ShadowDemon->CastSpell(target, SPELL_PURPLE_BEAM, true);
                            ShadowDemon->CastSpell(target, SPELL_PARALYZE, true);
                        }
                    }
                }
                ShadowDemonTimer = 35000;
            }else ShadowDemonTimer -= diff;

            if(GlobalTimer < diff)
            {
                if(ShadowBlastTimer < diff)
                {
                    DoCast(m_creature->getVictim(), SPELL_SHADOW_BLAST);
                    ShadowBlastTimer = 3000;
                    GlobalTimer += 1500;
                }else ShadowBlastTimer -= diff;

                if(FlameBurstTimer < diff)
                {
                    DoCast(m_creature, SPELL_FLAME_BURST);
                    FlameBurstTimer = 10000;
                    FlameBurstExplosionTimer = 500;
                    GlobalTimer += 3000;
                }else FlameBurstTimer -= diff;

                if(FlameBurstExplosionTimer < diff)
                {
                    DoFlameBurstExplosion();
                    FlameBurstExplosionTimer = FlameBurstTimer + 2000;
                }else FlameBurstExplosionTimer -= diff;
            }else GlobalTimer -= diff;
        }

        /** Phase 5 timers. Enrage spell **/
        if(Phase == 5)
        {
            if(EnrageTimer < diff)
            {
                // DoCast(m_creature, SPELL_ENRAGE);
                EnrageTimer = 15000;
            }else EnrageTimer -= diff;

            //TODO: MAIEVS TRAPS
        }
        
        if(Phase == 6) // Demonic Transformation
        {
            if(AnimationTimer < diff)
            {
                switch(DemonFormSequence)
                {
                    case 0:  // Make him stop moving!
                        m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
                        (*m_creature).GetMotionMaster()->Clear();
                        m_creature->HandleEmoteCommand(403);   // Fall down
                        DemonFormSequence++;
                        AnimationTimer = 500;
                        break;
                    case 1:
                        m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,404);  // Remain down
                        DemonFormSequence++;
                        AnimationTimer = 2000;
                        break;
                    case 2:
                        m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 0);
                        m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 0);
                        DoCast(m_creature, SPELL_DEMON_FORM);
                        m_creature->SetUInt32Value(OBJECT_FIELD_SCALE_X, 1073741824); // Make him bigger
                        m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 21322);  // Demon Form, because he sometimes didn't change appeariance after casting/removing SPELL_DEMON_FORM               
                        m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,404);
                        DemonFormSequence++;
                        AnimationTimer = 2000;
                        break;
                    case 3:
                        m_creature->HandleEmoteCommand(405); // Could you stand up please?
                        DemonFormSequence++;
                        AnimationTimer = 3000;
                        break;
                    case 4:
                        m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,0);
                        (*m_creature).GetMotionMaster()->Clear();
                        DemonFormSequence++;
                        AnimationTimer = 0;
                        GlobalTimer = 0;
                        ShadowDemonTimer = 15000;
                        ShadowBlastTimer = 1000;
                        FlameBurstTimer = 8000;
                        Phase = 4; // Demon Form Phase
                        break;
                    case 5:  // Shift back
                        m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
                        (*m_creature).GetMotionMaster()->Clear();
                        (*m_creature).GetMotionMaster()->Idle();
                        //m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
                        m_creature->HandleEmoteCommand(403);   // Fall down
                        DemonFormSequence++;
                        AnimationTimer = 500;
                        break;
                    case 6:
                        m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,404);  // Remain down
                        DemonFormSequence++;
                        AnimationTimer = 2000;
                        break;
                    case 7:
                        m_creature->SetUInt32Value(OBJECT_FIELD_SCALE_X, 1069547520); // Back to normal size
                        m_creature->SetUInt32Value(UNIT_FIELD_DISPLAYID, 21135); // Normal Form, because he sometimes didn't change appeariance after casting/removing SPELL_DEMON_FORM
                        m_creature->RemoveAurasDueToSpell(SPELL_DEMON_FORM);
                        m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,404);
                        DemonFormSequence++;
                        AnimationTimer = 2000;
                        break;
                    case 8:
                        m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY, 45479);
                        m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_DISPLAY+1, 45481);
                        m_creature->HandleEmoteCommand(405); // Could you stand up please?
                        DemonFormSequence++;
                        AnimationTimer = 3000;
                        break;
                    case 9:
                        m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,0);
                        (*m_creature).GetMotionMaster()->Mutate(new TargetedMovementGenerator<Creature>(*m_creature->getVictim()));
                        DemonFormSequence = 0;
                        AnimationTimer = 0;
                        GlobalTimer = 0;
                        ShearTimer = 20000 + (rand()%11 * 1000);
                        FlameCrashTimer = 30000;
                        ParasiticShadowFiendTimer = 25000;
                        DrawSoulTimer = 35000;
                        AgonizingFlamesTimer = 40000; // Not 35000 as before, since Draw Soul has the same timer.
                        if(!MaievGUID) Phase = 3; // Maiev has not yet been summoned, go back to phase 3
                        else Phase = 5; // Maiev has been summoned, go to phase 5.
                        break;
                }
            }else AnimationTimer -= diff;
        }
    }
};

struct MANGOS_DLL_SPEC npc_akama_illidanAI : public ScriptedAI
{
    npc_akama_illidanAI(Creature* c) : ScriptedAI(c)
    {
        pInstance = ((ScriptedInstance*)c->GetInstanceData());
        SetVariables();
    }

    /* Instance Data */
    ScriptedInstance* pInstance;

    /* Timers */
    uint32 TalkTimer;

    /* GUIDs */
    uint64 IllidanGUID;

    /* Generic */
    bool InCombat;
    bool IsTalking;
    bool RunAway;
    uint32 TalkCount;

    void SetVariables()
    {
        if(pInstance) pInstance->SetData("IllidanStormrageEvent", 0); // Not started
        IllidanGUID = 0;
        TalkTimer = 0;
        TalkCount = 0;

        InCombat = false;
        IsTalking = false;
        RunAway = false;

        m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 1); // Gossip flag
    }
    
    void EnterEvadeMode()
    {
        SetVariables();

        m_creature->DeleteThreatList();
        m_creature->RemoveAllAuras();
        m_creature->CombatStop();
        DoGoHome();
    }

    void BeginEvent()
    {
        InCombat = true;

        if(pInstance)
            IllidanGUID = pInstance->GetData64("IllidanStormrage");

        if(IllidanGUID)
        {
            Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID));
            if(Illidan)
            {
                // Start walking towards Illidan. Get exact positions and time later
                //m_creature->Relocate(Illidan->GetPositionX() + 20, Illidan->GetPositionY(), Illidan->GetPositionZ());
                //m_creature->SendMonsterMove(Illidan->GetPositionX() + 20, Illidan->GetPositionY(), Illidan->GetPositionZ(), 0, false, 20000);
                Illidan->RemoveAurasDueToSpell(SPELL_KNEEL); // Time for Illidan to stand up.
                Illidan->SetInCombat(); // Get ready to begin attacking
                m_creature->SetInCombat();
                ((boss_illidan_stormrageAI*)Illidan->AI())->TalkCount = 0; // First line of Akama-Illidan convo
                ((boss_illidan_stormrageAI*)Illidan->AI())->IsTalking = true; // Begin Talking
                ((boss_illidan_stormrageAI*)Illidan->AI())->InCombat = true; // Set Illidan in combat
                AttackStart(Illidan);
                Illidan->AI()->AttackStart(m_creature);
                IsTalking = true; // Prevent Akama from starting to attack him
                InCombat = true;
                m_creature->SetUInt32Value(UNIT_NPC_FLAGS, 0); // Prevent players from talking again
                DoCast(m_creature, SPELL_SELF_ROOT, true); // Prevent us from moving to attack Illidan
                Illidan->CastSpell(Illidan, SPELL_SELF_ROOT, true, 0, 0, Illidan->GetGUID()); // Prevent Illidan from running to attack us.
                if(m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE)) // SPELL_SELF_ROOT adds the skinning flag for some reason..
                    m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
                if(Illidan->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE))
                    Illidan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
            }
        }
    }
    
    void AttackStart(Unit *who)
    {
        if((!who) || IsTalking)
            return;

        if(who->isTargetableForAttack() && who!= m_creature)
        {
            DoStartMeleeAttack(who);

            if(!InCombat)
            {
                InCombat = true;
            }
        }
    }

    void DamageTaken(Unit *done_by, uint32 &damage)
    {
        if(IsTalking) IsTalking = false;
        if(damage > m_creature->GetHealth())
        {
            damage = 0;
            DoCast(m_creature, SPELL_HEALING_POTION);
        }
    }

    void DeleteFromThreatList()
    {
        if(!IllidanGUID) return; // If we do not have Illidan's GUID, do not proceed
        Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID)); // Create a pointer to Illidan
        if(!Illidan) return; // No use to continue if Illidan does not exist
        std::list<HostilReference *> i_threatlist = Illidan->getThreatManager().getThreatList();
        if(!i_threatlist.size()) return;// Threatlist is empty, do not proceed.
        std::list<HostilReference *>::iterator itr = i_threatlist.begin();
        std::advance(itr, 0);
        for( ; itr != i_threatlist.end(); ++itr)
        {
            if((*itr)->getUnitGuid() == m_creature->GetGUID()) // Loop through threatlist till our GUID is found in it.
            {
                (*itr)->removeReference(); // Delete ourself from his threatlist.
                break; // No need to continue anymore.
            }
        }
    }

    void UpdateAI(const uint32 diff)
    {   
        if(IllidanGUID)
        {
            Creature* Illidan = ((Creature*)Unit::GetUnit((*m_creature), IllidanGUID));
            if(Illidan)
            {
                if(((Illidan->GetHealth()*100 / Illidan->GetMaxHealth()) < 90) && (!RunAway))
                {
                    if(!((boss_illidan_stormrageAI*)Illidan->AI())->IsTalking) IsTalking = false; // Allow ourselves to attack Illidan if we're not talking with him

                    if(TalkTimer < diff)
                    {
                        switch(TalkCount)
                        {
                            case 0:
                                Illidan->Yell(SAY_AKAMA_MINION, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(Illidan, SOUND_AKAMA_MINION);
                                TalkTimer = 10000;
                                TalkCount = 1;
                                break;
                            case 1:
                                DoYell(SAY_AKAMA_LEAVE, LANG_UNIVERSAL, NULL);
                                DoPlaySoundToSet(m_creature, SOUND_AKAMA_LEAVE);
                                TalkTimer = 3000;
                                TalkCount = 2;
                                break;
                            case 2:
                                DoGoHome();
                                DeleteFromThreatList();
                                m_creature->SetVisibility(VISIBILITY_OFF);
                                DoCast(m_creature, SPELL_SELF_ROOT, true); // Root ourself so we don't go back to combat
                                IsTalking = true;
                                RunAway = true;
                                break;
                        }
                    }else TalkTimer -= diff;
                }
            }
        }

        // If we don't have a target, or is talking, or has run away, return
        if(!m_creature->SelectHostilTarget() || !m_creature->getVictim() || IsTalking || RunAway) return;
     
        DoMeleeAttackIfReady();
    }
};

bool GossipSelect_npc_akama_at_illidan(Player *player, Creature *_Creature, uint32 sender, uint32 action)
{
    if(action == GOSSIP_ACTION_INFO_DEF) // Time to begin the event
    {
        player->PlayerTalkClass->CloseGossip();
        ((npc_akama_illidanAI*)_Creature->AI())->BeginEvent();
    }
    return true;
}

bool GossipHello_npc_akama_at_illidan(Player *player, Creature *_Creature)
{
    player->ADD_GOSSIP_ITEM(0, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
    player->PlayerTalkClass->SendGossipMenu(10465, _Creature->GetGUID());

    return true;
}

CreatureAI* GetAI_boss_illidan_stormrage(Creature *_Creature)
{
    return new boss_illidan_stormrageAI (_Creature);
}

CreatureAI* GetAI_npc_akama_at_illidan(Creature *_Creature)
{
    return new npc_akama_illidanAI (_Creature);
}

void AddSC_boss_illidan()
{
    Script* newscript;

    newscript = new Script;
    newscript->Name = "boss_illidan_stormrage";
    newscript->GetAI = GetAI_boss_illidan_stormrage;
    m_scripts[nrscripts++] = newscript;

    newscript = new Script;
    newscript->Name = "boss_akama_illidan";
    newscript->GetAI = GetAI_npc_akama_at_illidan;
    newscript->pGossipHello = GossipHello_npc_akama_at_illidan;
    newscript->pGossipSelect = GossipSelect_npc_akama_at_illidan;
    m_scripts[nrscripts++] = newscript;
}
